package  com.example.tetris.logic.model

import androidx.compose.ui.geometry.Offset
import com.example.tetris.logic.Offset
import kotlin.math.absoluteValue
import kotlin.random.Random

data class Spirit(
    val shape: List<Offset> = emptyList(),
    val offset: Offset = Offset.Zero
) {
    val location = shape.map { it + offset }

    fun moveBy(step: Pair<Int, Int>): Spirit =
        copy(offset = offset + Offset(step.first, step.second))


    fun rotate(): Spirit {
        val newShape = shape.toMutableList()
        for (i in shape.indices) {
            newShape[i] = Offset(shape[i].y, -shape[i].x)
        }
        return copy(newShape)
    }


    fun adjustOffset(matrix: Pair<Int, Int>, yAdjust: Boolean = true): Spirit {

        val yOffset =
            if (yAdjust)
                (location.minByOrNull { it.y }?.takeIf { it.y < 0 }?.y?.absoluteValue
                    ?: 0).toInt() +
                        (location.maxByOrNull { it.y }
                            ?.takeIf { it.y > matrix.second - 1 }?.y?.let { matrix.second - 1 - it }
                            ?: 0).toInt()
            else 0

        val xOffset =
            (location.minByOrNull { it.x }?.takeIf { it.x < 0 }?.x?.absoluteValue ?: 0).toInt() +
                    (location.maxByOrNull { it.x }
                        ?.takeIf { it.x > matrix.first - 1 }?.x?.let { matrix.first - 1 - it }
                        ?: 0).toInt()
        return moveBy(xOffset to yOffset)
    }


    companion object {
        val Empty = Spirit()
    }
}

val SpiritType = listOf(
    listOf(Offset(1f, -1f), Offset(1f, 0f), Offset(0f, 0f), Offset(0f, 1f)),
    listOf(Offset(0f, -1f), Offset(0f, 0f), Offset(1f, 0f), Offset(1f, 1f)),
    listOf(Offset(0f, -1f), Offset(0f, 0f), Offset(0f, 1f), Offset(0f, 2f)),
    listOf(Offset(0f, 1f), Offset(0f, 0f), Offset(0f, -1f), Offset(1f, 0f)),
    listOf(Offset(1f, 0f), Offset(0f, 0f), Offset(1f, -1f), Offset(0f, -1f)),
    listOf(Offset(0f, -1f), Offset(1f, -1f), Offset(1f, 0f), Offset(1f, 1f)),
    listOf(Offset(1f, -1f), Offset(0f, -1f), Offset(0f, 0f), Offset(0f, 1f)),
)

fun Spirit.isValidInMatrix(bricks: List<Brick>, matrix: Pair<Int, Int>): Boolean {
    return location.none { location ->
        location.x < 0 || location.x > matrix.first - 1 || location.y > matrix.second - 1 || bricks.any {
            it.location.x == location.x && it.location.y == location.y
        }
    }
}

fun generateSpiritReverse(matrix: Pair<Int, Int>): List<Spirit> {
    return SpiritType.map {
        Spirit(it, Offset(Random.nextInt(matrix.first - 1), -1)).adjustOffset(matrix, false)
    }.shuffled()
}
